package pl.common.console;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.ObjectPool;
import org.codehaus.groovy.control.CompilationFailedException;

import pl.model.dao.BookDao;
import pl.model.service.SearchService;

public class Shell implements Runnable {

	private Socket socket;

	protected final Log log = LogFactory.getLog(getClass());

	private Map map;

	private ObjectPool pool;

	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	public void setMap(Map map) {
		this.map = map;
	}

	public Shell() {
		log.debug("Shell constructor");
	}

	public Shell(Map map) {
		this.map = map;
		log.debug("Shell constructor");
	}

	@Override
	public void run() {
		try {
			Binding binding = new Binding(map);
			GroovyShell shell = new GroovyShell(binding);

			PrintStream out = new PrintStream(socket.getOutputStream());
			out.println("Shell v 1.0");
			out.print("# ");
			BufferedReader in = new BufferedReader(new InputStreamReader(socket
					.getInputStream()));
			String command = null;
			do {
				command = in.readLine();
				log.debug("command " + command);
				System.out.println("command: " + command);
				Object o;
				try {
					if (!command.startsWith("exit")) {
						o = shell.evaluate(command);
						out.println(o);
					}
				} catch (RuntimeException e) {
					out.println("blad: " + e.getMessage());
					e.printStackTrace();
				}
				out.print("# ");
			} while (!command.startsWith("exit"));
			out.println("bye");
			socket.getOutputStream().flush();
			socket.close();
			pool.returnObject(this);
		} catch (IOException e) {

			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}

	public void setPool(ObjectPool pool) {
		this.pool = pool;
	}

	public void finalize() throws Throwable {
		log.debug("shell finalize");
		super.finalize();
	}

}
